import random
from operator import itemgetter, attrgetter


def use_sort():  # sort是list 列表中的方法，排序时会修改这个列表。list.sort(key,reverse)其中参数reverse表示排序结果是否反转，默认为False(不反转)即升序。
    my_list = [random.randint(0, 100) for i in range(10)]
    print(my_list)
    my_list.sort()
    print(my_list)

    # 参数key是带一个参数的函数，用来为每个元素提取比较值，默认为 None（即直接比较每个元素）。
    def new_key(in_list: list):  # 定义一个新的比较规则函数，传给参数key。此函数表示在比较列表中的每个元素时把每个元素提取为其下标为1的元素。
        return in_list[1]

    my_list = [[random.randint(0, 100) for i in range(3)] for j in range(3)]
    print(my_list)
    # 注意传给key的函数不加()。还有一种简便写法，使用匿名函数即lambda表达式：my_list.sort(key=lambda x:x[1])实现把列表中每个元素x提取为x[1]进行比较
    my_list.sort(key=new_key)
    print(my_list)
    # lambda的多重排序
    my_list = [[random.randint(0, 100) for i in range(3)] for j in range(3)]
    print(my_list)
    my_list.sort(key=lambda x: (x[1], x[2]))  # 每个元素x先按下[1]排序，遇到x[1]相等的元素x再按x[2]排。
    print(my_list)


def use_sorted():  # sorted是内置函数，对可迭代对象排序后返回一个有序的列表，并不改变本身这个对象。sorted(iterator,key,reverse)
    # 对集合的sorted
    a = {random.randint(0, 100) for i in range(10)}
    print(a)
    b = sorted(a)
    print(type(b), b)

    # 对元组内的对象进行sorted
    class Student:
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            self.score = score

        def __repr__(self):  # 功能与__str__相同，但可以返回非字符串类型的数据。
            return repr((self.name, self.age, self.score))  # 格式：return repr(要返回的数据)此时返回的是元组数据类型的

    s1 = Student("s1", 18, 98.5)
    s2 = Student("s2", 19, 88.5)
    s3 = Student("s3", 20, 78.5)
    old_s = (s1, s2, s3)  # 元组数据类型的，里面元素是自定义对象(自定义对象返回的是元组)。
    new_s = sorted(old_s, key=lambda x: x.score)  # sorted后返回的是列表数据类型的，里面元素是排好序的自定义对象(自定义对象返回的是元组)。
    print(old_s)
    print(new_s)
    # 利用opearator库中的itemgetter()、attrgetter()函数进行排序
    print(sorted(old_s, key=attrgetter('name','age')))  # attrgetter()用于可迭代对象里的元素是这样式的元素，这里还用了多重排序
    stu_class = [('jane', 'B', 12), ('john', 'A', 15), ('dave', 'B', 10), ]
    print(sorted(stu_class, key=itemgetter(2)))  # itemgetter()用于可迭代对象里的元素是可以取下标的元素类型


if __name__ == '__main__':
    use_sort()
    use_sorted()
